#pragma once
#include <vector>
#include <string>
#include <queue>
#include <unistd.h>
#include <pthread.h>
#include <iostream>

using namespace std;

namespace Tom
{
#define THREAD_NUM 10
   
    template<class T>
    class ThreadPool
    {
    private:
        int _num;
        std::vector<pthread_t> _threads;//线程环形数组队列
        std::queue<T> _tasks;//任务容器
        pthread_mutex_t _mtx;
        pthread_cond_t _cond;

    public:
        ThreadPool(int num = THREAD_NUM)
            :_threads(num), _num(num)
            {
                pthread_mutex_init(&_mtx, nullptr);
                pthread_cond_init(&_cond, nullptr);
            }
        
        ~ThreadPool()
        {
            pthread_mutex_destroy(&_mtx);
            pthread_cond_destroy(&_cond);
        }

        void init()
        {

        }

        void start()
        {
            //创建一批线程并启动
            for(int i = 0; i < _num; i++)
            {
                pthread_create(&_threads[i], nullptr, threadRoutine, this);
            }
        }

        static void* threadRoutine(void *args)
        {
            //避免线程等待直接分离
            pthread_detach(pthread_self());

            auto ptr = static_cast<ThreadPool<T>*>(args);

            while(true)
            {
                ptr->lockQueue();

                while(ptr->IsEmpty())
                {
                    ptr->threadwait();
                }
                //std::cout << "Thread Running--- " << pthread_self() << std::endl;
                T task = ptr->PopTask();
                ptr->unlockQueue();
                
                task();

                cout << task.getResult() << endl;
                //sleep(1);
            }
        }


        void lockQueue()
        {
            pthread_mutex_lock(&_mtx);
        }

        void unlockQueue()
        {
            pthread_mutex_unlock(&_mtx);
        }

        void threadwait()
        {
            pthread_cond_wait(&_cond, &_mtx);
        }

        void threadwakeup()
        {
            pthread_cond_signal(&_cond);
        }

        bool IsEmpty()
        {
            return _tasks.empty();
        }

        T PopTask()
        {
            T task = _tasks.front();
            _tasks.pop();

            return task;
        }

        void pushTask(const T& task)
        {
            lockQueue();
            _tasks.push(task);
            threadwakeup();
            unlockQueue();
        }

    };

    // 支持泛型
    template<class T>
    class Task
    {
    public:
        Task(T x = 0, T y = 0, char op = '+')
            :_x(x), _y(y), _op(op), _res(0), _err(0)
        {}

        // 重载运算操作
        void operator()()
        {
            // 简单计算
            switch(_op)
            {
                case '+':
                    _res = _x + _y;
                break;
                case '-':
                    _res = _x - _y;
                break;
                case '*':
                    _res = _x * _y;
                break;
                case '/':
                    if(_y == 0)
                        _err = -1;
                    else
                        _res = _x / _y;    
                break;
                case '%':
                    if(_y == 0)
                        _err = -2;
                    else
                        _res = _x % _y;    
                break;
                default:
                    _err = -3;
                break;
            }
        }

        // 获取计算结果
        std::string getResult()
        {
            // 根据错误标识，返回计算结果
            std::string ret = std::to_string(_x) + " " + _op + " " + std::to_string(_y);
            
            if(_err)
            {
                ret += " error";

                // 判读是 / 错误还是 % 错误
                if(_err == -1)
                    ret += " [-1] \t / 0 引发了错误";
                else if(_err == -2)
                    ret += " [-2] \t % 0 引发了错误";
                else
                    ret += " [-3] \t 不合法的操作符，只能为 [+-*/%]";
            }
            else
            {
                ret += " = " + std::to_string(_res);
            }

            return ret;
        }

    private:
        T _x;
        T _y;
        char _op; // 运算符
        T _res; // 结果
        int _err; // 错误标识
    };
                        
}
